"""PPG处理器高级使用示例

展示PPG处理器的高级功能，包括：
1. 批量处理多个信号
2. 自定义配置参数
3. Pipeline性能比较
4. 错误处理和异常情况
5. 结果导出和保存

作者: PPG算法包开发团队
版本: 2.0.0
"""

import numpy as np
import logging
import time
from typing import List, Dict, Any
import json
from pathlib import Path

try:
    from ..core import get_global_manager, PPGSignal, PPGResults
    from ..config.pipeline_config import PipelineConfig
    from ..config.default_configs import get_config_by_name
except ImportError:
    # 处理直接运行时的导入问题
    import sys
    sys.path.append(str(Path(__file__).parent.parent))
    from core import get_global_manager, PPGSignal, PPGResults
    from config.pipeline_config import PipelineConfig
    from config.default_configs import get_config_by_name

# 设置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


def advanced_ppg_processing_example():
    """高级PPG处理示例
    
    演示高级配置和自定义参数的使用
    """
    print("=" * 60)
    print("PPG处理器高级使用示例")
    print("=" * 60)
    
    # 1. 创建多种类型的测试信号
    print("\n1. 创建测试信号集")
    test_signals = create_test_signals()
    print(f"创建了 {len(test_signals)} 个测试信号")
    
    # 2. 自定义配置示例
    print("\n2. 自定义配置示例")
    demonstrate_custom_configurations(test_signals[0])
    
    # 3. Pipeline性能比较
    print("\n3. Pipeline性能比较")
    compare_pipeline_performance(test_signals)
    
    # 4. 错误处理演示
    print("\n4. 错误处理演示")
    demonstrate_error_handling()
    
    print("\n" + "=" * 60)
    print("高级示例完成")
    print("=" * 60)


def batch_processing_example():
    """批量处理示例
    
    演示如何批量处理多个PPG信号
    """
    print("=" * 60)
    print("PPG批量处理示例")
    print("=" * 60)
    
    # 1. 创建批量测试数据
    print("\n1. 创建批量测试数据")
    batch_signals = create_batch_test_data(num_signals=10)
    print(f"创建了 {len(batch_signals)} 个信号用于批量处理")
    
    # 2. 使用管理器进行批量处理
    print("\n2. 批量处理执行")
    manager = get_global_manager()
    
    start_time = time.time()
    results = manager.batch_process(
        signals=batch_signals,
        pipeline_name="batch_custom",
        pipeline_type="custom",
        config="fast",
        sampling_rate=100.0
    )
    processing_time = time.time() - start_time
    
    print(f"✓ 批量处理完成")
    print(f"  处理时间: {processing_time:.2f} 秒")
    print(f"  平均每信号: {processing_time/len(batch_signals):.3f} 秒")
    
    # 3. 分析批量结果
    print("\n3. 批量结果分析")
    analyze_batch_results(results)
    
    # 4. 导出结果
    print("\n4. 导出批量结果")
    export_batch_results(results, "batch_results.json")


def create_test_signals() -> List[Dict[str, Any]]:
    """创建多种类型的测试信号
    
    返回:
        List[Dict]: 测试信号列表
    """
    signals = []
    sampling_rate = 100.0
    duration = 30.0
    t = np.linspace(0, duration, int(sampling_rate * duration))
    
    # 1. 正常心率信号 (70 BPM)
    normal_hr = 70
    signal1 = generate_ppg_signal(t, normal_hr, noise_level=0.1)
    signals.append({
        'data': signal1,
        'sampling_rate': sampling_rate,
        'type': 'normal',
        'expected_hr': normal_hr,
        'subject_id': 'test_001'
    })
    
    # 2. 高心率信号 (120 BPM)
    high_hr = 120
    signal2 = generate_ppg_signal(t, high_hr, noise_level=0.15)
    signals.append({
        'data': signal2,
        'sampling_rate': sampling_rate,
        'type': 'high_hr',
        'expected_hr': high_hr,
        'subject_id': 'test_002'
    })
    
    # 3. 低心率信号 (50 BPM)
    low_hr = 50
    signal3 = generate_ppg_signal(t, low_hr, noise_level=0.08)
    signals.append({
        'data': signal3,
        'sampling_rate': sampling_rate,
        'type': 'low_hr',
        'expected_hr': low_hr,
        'subject_id': 'test_003'
    })
    
    # 4. 高噪声信号
    noisy_signal = generate_ppg_signal(t, 75, noise_level=0.5)
    signals.append({
        'data': noisy_signal,
        'sampling_rate': sampling_rate,
        'type': 'noisy',
        'expected_hr': 75,
        'subject_id': 'test_004'
    })
    
    # 5. 不规律心率信号
    irregular_signal = generate_irregular_ppg_signal(t, base_hr=80)
    signals.append({
        'data': irregular_signal,
        'sampling_rate': sampling_rate,
        'type': 'irregular',
        'expected_hr': 80,
        'subject_id': 'test_005'
    })
    
    return signals


def generate_ppg_signal(t: np.ndarray, heart_rate: float, noise_level: float = 0.1) -> np.ndarray:
    """生成模拟PPG信号
    
    参数:
        t: 时间数组
        heart_rate: 心率 (BPM)
        noise_level: 噪声水平
        
    返回:
        np.ndarray: PPG信号
    """
    frequency = heart_rate / 60  # Hz
    
    # 基础正弦波
    signal = np.sin(2 * np.pi * frequency * t)
    
    # 添加谐波（更真实的PPG形状）
    signal += 0.3 * np.sin(2 * np.pi * 2 * frequency * t)
    signal += 0.1 * np.sin(2 * np.pi * 3 * frequency * t)
    
    # 添加噪声
    noise = np.random.normal(0, noise_level, len(t))
    signal += noise
    
    # 添加基线漂移
    baseline_drift = 0.1 * np.sin(2 * np.pi * 0.05 * t)  # 0.05 Hz漂移
    signal += baseline_drift
    
    return signal


def generate_irregular_ppg_signal(t: np.ndarray, base_hr: float) -> np.ndarray:
    """生成不规律心率的PPG信号
    
    参数:
        t: 时间数组
        base_hr: 基础心率
        
    返回:
        np.ndarray: 不规律PPG信号
    """
    signal = np.zeros_like(t)
    current_time = 0
    
    while current_time < t[-1]:
        # 随机变化心率 (±20%)
        hr_variation = np.random.uniform(0.8, 1.2)
        current_hr = base_hr * hr_variation
        interval = 60.0 / current_hr  # 心跳间隔
        
        # 找到当前时间点的索引
        start_idx = np.searchsorted(t, current_time)
        end_idx = np.searchsorted(t, current_time + interval)
        
        if end_idx < len(t):
            # 生成单个心跳
            beat_t = t[start_idx:end_idx] - current_time
            beat_signal = np.sin(2 * np.pi * beat_t / interval)
            beat_signal += 0.3 * np.sin(2 * np.pi * 2 * beat_t / interval)
            
            signal[start_idx:end_idx] += beat_signal
        
        current_time += interval
    
    # 添加噪声
    noise = np.random.normal(0, 0.15, len(t))
    signal += noise
    
    return signal


def demonstrate_custom_configurations(test_signal: Dict[str, Any]):
    """演示自定义配置的使用
    
    参数:
        test_signal: 测试信号
    """
    print("--- 自定义配置演示 ---")
    
    # 1. 高精度配置
    print("\n1. 高精度配置")
    high_precision_config = {
        "name": "high_precision",
        "sampling_rate": 100.0,
        "preprocessing": {
            "outlier_detection": {
                "enabled": True,
                "method": "median_filter",
                "window_size": 15,
                "threshold_percentile": 95
            },
            "smoothing": {
                "enabled": True,
                "method": "savgol",
                "window_length": 11,
                "polynomial_order": 3
            },
            "detrending": {
                "enabled": True,
                "method": "polynomial",
                "order": 2
            },
            "filtering": {
                "enabled": True,
                "method": "butterworth",
                "order": 4,
                "low_cutoff": 0.5,
                "high_cutoff": 8.0
            }
        },
        "peak_detection": {
            "height_percentile": 75,
            "distance_min": 40,
            "prominence_factor": 0.3,
            "width_min": 3
        }
    }
    
    try:
        manager = get_global_manager()
        results = manager.process_signal(
            signal_data=test_signal,
            pipeline_name="high_precision_demo",
            pipeline_type="custom",
            config=high_precision_config
        )
        
        print(f"✓ 高精度配置处理成功")
        print(f"  检测峰值: {len(results.peaks)}")
        print(f"  平均心率: {results.mean_heart_rate:.1f} BPM")
        
    except Exception as e:
        print(f"✗ 高精度配置处理失败: {e}")
    
    # 2. 快速处理配置
    print("\n2. 快速处理配置")
    fast_config = {
        "name": "fast_processing",
        "sampling_rate": 100.0,
        "preprocessing": {
            "outlier_detection": {"enabled": False},
            "smoothing": {"enabled": False},
            "detrending": {"enabled": False},
            "filtering": {
                "enabled": True,
                "method": "butterworth",
                "order": 2,
                "low_cutoff": 1.0,
                "high_cutoff": 5.0
            }
        },
        "peak_detection": {
            "height_percentile": 60,
            "distance_min": 30,
            "prominence_factor": 0.2,
            "width_min": 1
        }
    }
    
    try:
        results = manager.process_signal(
            signal_data=test_signal,
            pipeline_name="fast_demo",
            pipeline_type="custom",
            config=fast_config
        )
        
        print(f"✓ 快速配置处理成功")
        print(f"  检测峰值: {len(results.peaks)}")
        print(f"  平均心率: {results.mean_heart_rate:.1f} BPM")
        
    except Exception as e:
        print(f"✗ 快速配置处理失败: {e}")


def compare_pipeline_performance(test_signals: List[Dict[str, Any]]):
    """比较不同Pipeline的性能
    
    参数:
        test_signals: 测试信号列表
    """
    print("--- Pipeline性能比较 ---")
    
    manager = get_global_manager()
    
    # 测试配置
    configs_to_test = [
        ("custom_fast", "custom", "fast"),
        ("custom_accurate", "custom", "accurate"),
    ]
    
    # 如果NeuroKit2可用，添加到测试中
    try:
        manager.create_pipeline("neurokit2")
        configs_to_test.append(("neurokit2_default", "neurokit2", None))
    except (ImportError, Exception):
        print("NeuroKit2不可用，跳过NeuroKit2性能测试")
    
    results_summary = []
    
    for config_name, pipeline_type, config in configs_to_test:
        print(f"\n测试配置: {config_name}")
        
        total_time = 0
        total_peaks = 0
        total_signals = 0
        errors = 0
        
        for i, signal in enumerate(test_signals):
            try:
                start_time = time.time()
                
                result = manager.process_signal(
                    signal_data=signal,
                    pipeline_name=f"{config_name}_{i}",
                    pipeline_type=pipeline_type,
                    config=config
                )
                
                processing_time = time.time() - start_time
                total_time += processing_time
                total_peaks += len(result.peaks)
                total_signals += 1
                
            except Exception as e:
                errors += 1
                logger.error(f"信号 {i} 处理失败: {e}")
        
        # 计算统计信息
        avg_time = total_time / max(total_signals, 1)
        avg_peaks = total_peaks / max(total_signals, 1)
        success_rate = (total_signals / len(test_signals)) * 100
        
        results_summary.append({
            'config': config_name,
            'avg_time': avg_time,
            'avg_peaks': avg_peaks,
            'success_rate': success_rate,
            'total_time': total_time,
            'errors': errors
        })
        
        print(f"  平均处理时间: {avg_time:.3f} 秒")
        print(f"  平均检测峰值: {avg_peaks:.1f}")
        print(f"  成功率: {success_rate:.1f}%")
    
    # 显示性能总结
    print(f"\n--- 性能总结 ---")
    print(f"{'配置':<20} {'平均时间(s)':<12} {'平均峰值':<10} {'成功率(%)':<10}")
    print("-" * 55)
    
    for result in results_summary:
        print(f"{result['config']:<20} {result['avg_time']:<12.3f} "
              f"{result['avg_peaks']:<10.1f} {result['success_rate']:<10.1f}")


def demonstrate_error_handling():
    """演示错误处理和异常情况
    """
    print("--- 错误处理演示 ---")
    
    manager = get_global_manager()
    
    # 1. 空信号
    print("\n1. 空信号处理")
    try:
        empty_signal = np.array([])
        result = manager.process_signal(
            signal_data=empty_signal,
            sampling_rate=100.0,
            pipeline_name="empty_test"
        )
        print("✗ 空信号应该抛出异常")
    except Exception as e:
        print(f"✓ 正确处理空信号异常: {type(e).__name__}")
    
    # 2. 无效采样率
    print("\n2. 无效采样率")
    try:
        test_signal = np.random.randn(1000)
        result = manager.process_signal(
            signal_data=test_signal,
            sampling_rate=0,  # 无效采样率
            pipeline_name="invalid_sr_test"
        )
        print("✗ 无效采样率应该抛出异常")
    except Exception as e:
        print(f"✓ 正确处理无效采样率: {type(e).__name__}")
    
    # 3. 信号过短
    print("\n3. 信号过短")
    try:
        short_signal = np.random.randn(10)  # 只有10个点
        result = manager.process_signal(
            signal_data=short_signal,
            sampling_rate=100.0,
            pipeline_name="short_test"
        )
        print(f"✓ 短信号处理完成，检测峰值: {len(result.peaks)}")
    except Exception as e:
        print(f"✓ 短信号异常处理: {type(e).__name__}")
    
    # 4. 无效Pipeline类型
    print("\n4. 无效Pipeline类型")
    try:
        test_signal = np.random.randn(1000)
        result = manager.process_signal(
            signal_data=test_signal,
            sampling_rate=100.0,
            pipeline_name="invalid_type_test",
            pipeline_type="invalid_type"
        )
        print("✗ 无效Pipeline类型应该抛出异常")
    except Exception as e:
        print(f"✓ 正确处理无效Pipeline类型: {type(e).__name__}")


def create_batch_test_data(num_signals: int = 10) -> List[Dict[str, Any]]:
    """创建批量测试数据
    
    参数:
        num_signals: 信号数量
        
    返回:
        List[Dict]: 批量测试信号
    """
    signals = []
    sampling_rate = 100.0
    duration = 20.0  # 较短的信号用于批量测试
    
    for i in range(num_signals):
        t = np.linspace(0, duration, int(sampling_rate * duration))
        
        # 随机心率 (60-120 BPM)
        heart_rate = np.random.uniform(60, 120)
        
        # 随机噪声水平
        noise_level = np.random.uniform(0.05, 0.3)
        
        signal = generate_ppg_signal(t, heart_rate, noise_level)
        
        signals.append({
            'data': signal,
            'sampling_rate': sampling_rate,
            'subject_id': f'batch_{i:03d}',
            'expected_hr': heart_rate,
            'noise_level': noise_level
        })
    
    return signals


def analyze_batch_results(results: List[PPGResults]):
    """分析批量处理结果
    
    参数:
        results: 批量处理结果
    """
    successful_results = [r for r in results if len(r.peaks) > 0]
    failed_results = [r for r in results if len(r.peaks) == 0]
    
    print(f"成功处理: {len(successful_results)}/{len(results)}")
    print(f"失败处理: {len(failed_results)}")
    
    if successful_results:
        heart_rates = [r.mean_heart_rate for r in successful_results]
        peak_counts = [len(r.peaks) for r in successful_results]
        
        print(f"\n心率统计:")
        print(f"  平均心率: {np.mean(heart_rates):.1f} ± {np.std(heart_rates):.1f} BPM")
        print(f"  心率范围: {np.min(heart_rates):.1f} - {np.max(heart_rates):.1f} BPM")
        
        print(f"\n峰值统计:")
        print(f"  平均峰值数: {np.mean(peak_counts):.1f} ± {np.std(peak_counts):.1f}")
        print(f"  峰值范围: {np.min(peak_counts)} - {np.max(peak_counts)}")
        
        # 质量统计
        quality_scores = []
        for r in successful_results:
            if r.quality_results:
                quality_scores.append(r.quality_results.quality_score)
        
        if quality_scores:
            print(f"\n质量统计:")
            print(f"  平均质量评分: {np.mean(quality_scores):.3f} ± {np.std(quality_scores):.3f}")
            print(f"  质量范围: {np.min(quality_scores):.3f} - {np.max(quality_scores):.3f}")


def export_batch_results(results: List[PPGResults], filename: str):
    """导出批量结果到JSON文件
    
    参数:
        results: 批量处理结果
        filename: 输出文件名
    """
    try:
        export_data = []
        
        for i, result in enumerate(results):
            result_dict = {
                'signal_id': i,
                'pipeline_name': result.pipeline_name,
                'peaks_count': len(result.peaks),
                'mean_heart_rate': result.mean_heart_rate,
                'peaks': result.peaks.tolist() if len(result.peaks) > 0 else [],
                'heart_rates': result.heart_rates.tolist() if result.heart_rates is not None else None,
                'processing_info': result.processing_info
            }
            
            # 添加HRV结果
            if result.hrv_results:
                result_dict['hrv'] = {
                    'rmssd': result.hrv_results.rmssd,
                    'sdnn': result.hrv_results.sdnn,
                    'pnn50': result.hrv_results.pnn50,
                    'mean_rr': result.hrv_results.mean_rr,
                    'lf_hf_ratio': result.hrv_results.lf_hf_ratio
                }
            
            # 添加质量结果
            if result.quality_results:
                result_dict['quality'] = {
                    'overall_score': result.quality_results.quality_score,
                    'quality_grade': result.quality_results.quality_grade,
                    'snr': result.quality_results.snr,
                    'peak_regularity': result.quality_results.peak_regularity
                }
            
            export_data.append(result_dict)
        
        # 保存到文件
        output_path = Path(filename)
        with open(output_path, 'w', encoding='utf-8') as f:
            json.dump(export_data, f, indent=2, ensure_ascii=False)
        
        print(f"✓ 结果已导出到: {output_path.absolute()}")
        
    except Exception as e:
        print(f"✗ 导出失败: {e}")


if __name__ == "__main__":
    # 运行高级示例
    advanced_ppg_processing_example()
    
    # 运行批量处理示例
    batch_processing_example()